package com.markyao.handler;

import com.github.benmanes.caffeine.cache.Cache;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j(topic = "m.JwtHandler")
public class JwtHandler {
    private static final String jwtToken = "123456Mky!@#$$";
    private static final long expireTime=24 * 60 * 60 * 1000;
    @Autowired
    Cache<String,String> tokenCache;

    public String createToken(String username,String pwd){
        String token=createToken0(username,pwd);
        //存进cache
        putTokenCache(token,token,username,pwd);
        return token;
    }

    private void putTokenCache(String token,String tokenVal,String un,String pwd){
        tokenCache.policy().expireVariably().ifPresent(policy->{
            policy.put(token,tokenVal,expireTime*2, TimeUnit.MILLISECONDS);
        });
        tokenCache.policy().expireVariably().ifPresent(p->{
            p.put(token+"_user",un+"<:_:>"+pwd,expireTime*2,TimeUnit.MILLISECONDS);
        });
    }
    private String createToken0(String username,String pwd){
        Map<String, Object> claims = getUsermap(username, pwd);
        JwtBuilder jwtBuilder = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, jwtToken) // 签发算法，秘钥为jwtToken
                .setClaims(claims) // body数据，要唯一，自行设置
                .setIssuedAt(new Date()) // 设置签发时间
//                .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000));// 一天的有效时间
                .setExpiration(new Date(System.currentTimeMillis() + expireTime));// 一分钟的有效时间

        String token = jwtBuilder.compact();


        return token;
    }

    private Map<String, Object> getUsermap(String username, String pwd) {
        Map<String,Object> claims = new HashMap<>();
        claims.put("username", username);
        claims.put("password", pwd);
        return claims;
    }

    public Map<String, Object> checkToken(String token){
        try {
            //先查缓存
            String tk = tokenCache.getIfPresent(token);
            if (tk==null){
                //缓存都没有,表示已经过期-->无药可救
                return null;
            }
            //缓存存在的话,jwt检查一下
            Jwt parse = null;
            try {
                parse = Jwts.parser().setSigningKey(jwtToken).parse(tk);
                boolean signed = Jwts.parser().isSigned(tk);
            } catch (ExpiredJwtException e) {
                //续约token
                log.info("续约token.");
                String s = tokenCache.getIfPresent(token + "_user");
                String[] user = s.split("<:_:>");
                String newTk = createToken0(user[0], user[1]);
                putTokenCache(token,newTk,user[0],user[1]);
                return getUsermap(user[0], user[1]);
            } catch (MalformedJwtException e) {
                e.printStackTrace();
            } catch (SignatureException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
            if (parse!=null){
                if (parse.getBody()!=null){
                    return (Map<String, Object>) parse.getBody();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }


}
